package com.cyys.modules.core.utils.exportExcel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.cyys.common.thirdInterface.ThirdConfig;
import com.cyys.common.utils.StringUtil;
import com.cyys.common.utils.date.DateUtil;
import com.google.common.collect.Lists;
import org.apache.poi.ss.usermodel.*;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 导出excel/csv
 */
public class CommonExportUtil {

    public static HorizontalCellStyleStrategy style() {
        // 头部的样式
        WriteCellStyle headStyle = new WriteCellStyle();
        headStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont headFont = new WriteFont();
        headFont.setBold(true);
        headFont.setFontHeightInPoints((short) 14);
        headStyle.setWriteFont(headFont);
        headStyle.setWrapped(true);

        // 内容的样式
        WriteCellStyle contentStyle = new WriteCellStyle();
        contentStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        contentStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints((short) 12);
        contentStyle.setWriteFont(contentWriteFont);
        contentStyle.setBorderTop(BorderStyle.THIN);
        contentStyle.setBorderBottom(BorderStyle.THIN);
        contentStyle.setBorderLeft(BorderStyle.THIN);
        contentStyle.setBorderRight(BorderStyle.THIN);
        contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//		contentStyle.setWrapped(true); 自动换行
        return new HorizontalCellStyleStrategy(headStyle, contentStyle);
    }

    /**
     * @param colList 导出字段list
     * @param rowData 行data
     * @param clazz
     * @return
     */
    public static List<Object> createRow(List<Map<String,String>> colList, Object rowData, Class clazz){
        List<Object> row= new ArrayList<Object>();
        colList.stream().forEach(obj -> {
            String field = obj.get("field");
            Method m = null;
            try {
                m = clazz.getMethod("get" + StringUtil.upperCaseFirst(field));
                Object value = null;
                try {
                    value = m.invoke(rowData);
                    if (value != null) {
                        if (value instanceof Date) {
                            if ("dateCreate".equals(field)) {
                                row.add(com.cyys.common.utils.date.DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss"));
                            } else {
                                row.add(DateUtil.format((Date) value, "yyyy-MM-dd"));
                            }
                        } else if (field.toLowerCase().endsWith("img") || field.toLowerCase().endsWith("imgs") || field.toLowerCase().endsWith("image") || field.toLowerCase().endsWith("images")) {
                            if (StringUtil.isNotBlank(value.toString())) {
                                String imgUrls = ThirdConfig.ALY_OSS_ENDPOINT + value.toString();
                                imgUrls = imgUrls.replaceAll(",", ("," + imgUrls));
                                row.add(imgUrls);
                            } else {
                                row.add("");
                            }
                        } else {
                            row.add(value.toString());
                        }
                    } else {
                        row.add("");
                    }
                } catch (IllegalAccessException e) {
                    row.add("");
                } catch (InvocationTargetException e) {
                    row.add("");
                }
            } catch (NoSuchMethodException e) {
                row.add("");
            }
        });
        return row;
    }

    /**
     * 组装表头和字段map
     * @param cols 格式：field1,title1;field2,title2;field3,title1
     * @return
     */
    public static Map<String, Object> getHeadList(String cols){
        String[] colArr= cols.split(";");
        List<List<String>> headList = Lists.newArrayList();//表头
        List<Map<String,String>> colList= Arrays.asList(colArr).stream().map(d->
                {
                    String[] arr= d.split(",");
                    Map<String,String> map = new HashMap<String,String>(){{
                        put("field", arr[0]);
                        put("title", arr[1]);
                    }};

                    List<String> head= new ArrayList(){{
                        add(arr[1]);
                    }};
                    headList.add(head);
                    return map;
                }
        ).collect(Collectors.toList());
        return new HashMap(){{
            put("headList",headList);
            put("colList",colList);
        }};
    }

    /**
     * @return
     */
    public static void createExcelWriter(HttpServletResponse response, String cols, List dataList)throws Exception{
        Map<String, Object> map= CommonExportUtil.getHeadList(cols);
        List<List<String>> headList = (List<List<String>>) map.get("headList");//表头
        List<Map<String,String>> colList= (List<Map<String, String>>) map.get("colList");

        List<List<Object>> data = new ArrayList<List<Object>>();
        if(dataList!=null && dataList.size()>0){
//            data= dataList.stream().map(rowData-> CommonExportUtil.createRow(colList, rowData, rowData.getClass())).collect(Collectors.toList());
            dataList.stream().forEach(rowData-> {
                data.add(CommonExportUtil.createRow(colList, rowData, rowData.getClass()));
            });
        }
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(CommonExportUtil.style())// 设置统一的表头、表内容样式
                .build();
        WriteSheet sheet = EasyExcel.writerSheet(0, "列表导出")
                .registerWriteHandler(new DataColumnWidthStrategy(colList))// 指定这个sheet的每个列的宽度
                .head(headList)// 自定义多级复杂表头
                .build();
        excelWriter.write(data, sheet);
        excelWriter.finish(); //此处会关闭流的
    }
}